package vip.xiaonuo.auth.modular.login.controller;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import vip.xiaonuo.auth.api.SaBaseLoginUserApi;
import vip.xiaonuo.common.config.ConfigProperties;
import vip.xiaonuo.auth.core.pojo.SaBaseClientLoginUser;
import vip.xiaonuo.auth.modular.login.enums.AuthDeviceTypeEnum;
import vip.xiaonuo.auth.modular.login.service.AuthService;
import vip.xiaonuo.common.cache.CommonCacheOperator;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.dev.api.DevConfigApi;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;

@Slf4j
@RestController
@RequestMapping("/auth/wxmp")
@Api(value = "微信公众号网页授权登录")
public class AuthWxmpController {
    private WxMpService wxMpService;
    @Resource
    private ConfigProperties configProperties;
    @Resource
    private CommonCacheOperator commonCacheOperator;
    @Resource(name = "clientLoginUserApi")
    private SaBaseLoginUserApi clientLoginUserApi;
    @Resource
    private AuthService authService;
    @Resource
    private DevConfigApi devConfigApi;

    @PostConstruct
    public void init() {
        WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
        configStorage.setAppId(configProperties.getWechatConf().getAppId());
        configStorage.setSecret(configProperties.getWechatConf().getSecret());
        configStorage.setToken(configProperties.getWechatConf().getToken());
        configStorage.setAesKey(configProperties.getWechatConf().getAseKey());
        wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(configStorage);
    }

    /**
     * 获得获取openId的回调地址
     *
     * @return
     */
    @RequestMapping("/login")
    public void getOauthUrl(HttpServletResponse response) throws IOException {
        String baseUrl = devConfigApi.getValueByKey("BACKEND_BASE_URL");
        if (ObjectUtil.isEmpty(baseUrl)) throw new CommonException("服务端URL未正确配置");
        String requestUrl = String.format("%s/auth/wxmp/callback", baseUrl);
        //获得到请求的回调地址，需要获得到用户的unionId,所以不能使用静默授权
        String callbackUrl = wxMpService.oauth2buildAuthorizationUrl(requestUrl, "snsapi_userinfo", "DEFAULT");
        log.info("获取openId回调地址={}", callbackUrl);
        response.sendRedirect(callbackUrl);
    }

    @RequestMapping("/callback")
    public void getSnsOpenId(HttpServletRequest request, HttpServletResponse response) throws WxErrorException, IOException {
        String h5_frontend_base_url = devConfigApi.getValueByKey("H5_FRONTEND_BASE_URL");
        if (ObjectUtil.isEmpty(h5_frontend_base_url)) throw new CommonException("H5_FRONTEND_BASE_URL未正确配置");

        String loginKey = UUID.randomUUID().toString();
        String code = request.getParameter("code");
        log.info("获得到code={}", code);

        try {
            WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
            log.info("微信授权登录={}", wxMpOAuth2AccessToken.toString());
            WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, "zh_CN");
            log.info("获取微信用户信息={}", wxMpUser.toString());
            SaBaseClientLoginUser loginUser = clientLoginUserApi.getClientUserByWxmpOpenId(wxMpUser.getOpenId());
            if (loginUser == null) {// The user can't be found by openid, need to execute binding account and openid.
                commonCacheOperator.put(String.format(ConfigProperties.WXMP_BINDING_KEY, loginKey),
                        JSON.toJSONString(wxMpUser), 60 * 60 * 24); // 1天内有效
                response.sendRedirect(String.format("%s/pages/common/login/index?loginKey=%s", h5_frontend_base_url, loginKey));
            } else { // 直接执行登录
                String token = authService.execLoginC(loginUser, AuthDeviceTypeEnum.H5.getValue());
                response.sendRedirect(String.format("%s/pages/common/home/index?token=%s", h5_frontend_base_url, token));
            }
        } catch (WxErrorException e) {
            log.error("微信授权绑定异常", e);
            throw e;
        }
    }
}
